#coding=utf-8

require "aio/core"

class Aio::Module::Cmd::H3C::DisplayInterface < Aio::Module::Cmd::H3C
	
	include Aio::Module
	
	def initialize
		super({
			:cmd_full 	=> "display interface",
			:cmd_short  => "dis inter",
			:author			=> "Elin",
			:description => "This is H3C Command# display interface",
			:ranking		=> Ranking_1,
			:platform   => "switch",
			:benchmark  => {
				:duplex						=> ["=~", /full/],
				:input_errors			=> ["<", 10],
				:output_errors		=> ["<", 10],
				:runts						=> ["<", 10],
				:giants						=> ["<", 10],
				:throttles				=> ["<", 10],
				:crc 							=> ["<", 1000],
				:frame						=> ["<", 10],
				:overruns					=> ["<", 10],
				:aborts						=> ["<", 10],
				:underruns				=> ["<", 10],
				:deferred					=> ["<", 10],
				:carrier					=> ["<", 10],
				:input_drops			=> ["<", 10],
				:output_drops			=> ["<", 10],
				:collisions 			=> ["<", 10],
				:last_collisions 	=> ["<", 10],
				:lost_carrier 		=> ["<", 10],
			}
		})
	end

	Reg_Bridge_Aggregation = /Bridge-Aggregation/
	Reg_Ethernet    = /Ethernet/
	Reg_Loopback 		= /LoopBack/
	Reg_Vlanif			= /Vlan/

	def parse
		cont = self.context.dup
		useful[:interface] = {}
		loop do 
			cont.readline_range(/.*/, reg_blank) do |cont_layer|
				switch_iface(cont_layer)
			end	
		end 
	end

	def switch_iface(context)
		i = 0
		while(i < 5)
			if context[i] =~ /current/
				break
			end
			i += 1
		end
		case context[i]
		when Reg_Bridge_Aggregation
			parse_bridge(context)
		when Reg_Ethernet
			parse_eth(context)
		when Reg_Loopback
			parse_loopback(context)
		when Reg_Vlanif
			parse_vlanif(context)
		end
	end

	def parse_bridge(context)
		iface = {}
		iface_id = nil
		context.readline_match_block(/(?<iface_id>Bridge-Aggregation\d+) current state\s?:\s?(?<state>.*)/) do |block|
			iface_id = block[:iface_id]
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :state)
		end
		context.readline_match_block(/IP Packet Frame Type: PKTFMT_ETHNT_2, Hardware Address: (?<mac>.*)/) do |block|
			block.update(iface, :mac)
		end
		context.readline_match_block(/Description: (?<description>.*)/) do |block|
			block.update(iface, :description)
		end
		context.readline_match_block(/(?<speed>.*) mode, (?<duplex>.*) mode/) do |block|
			block.update(iface, :speed)
			block.warning_serious(iface, :duplex, self) if iface[:state] =~ /UP/
		end
		context.readline_match_block(/Port link-type: (?<link_type>.*)/) do |block|
			block.update(iface, :link_type)
		end
		same_line_1(context, iface, iface_id) if iface[:state] =~ /UP/
	end

	def parse_eth(context)
		iface = {}
		iface_id = nil
		context.readline_match_block(/(?<iface_id>.*) current state\s?:\s?(?<state>.*)/) do |block|
			iface_id = block[:iface_id].strip
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :state)
		end
		return if iface.nil?
		context.readline_match_block(/Hardware Address: (?<mac>.*)/) do |block|
			block.update(iface, :mac)
		end
		context.readline_match_block(/Description: (?<description>.*)/) do |block|
			block.update(iface, :description)
		end
		context.readline_match_block(/(?<speed>.*) mode, (?<duplex>.*) mode/) do |block|
			block.update(iface, :speed)
			block.warning_serious(iface, :duplex, self) if iface[:state] =~ /UP/
		end
		same_line_1(context, iface, iface_id) if iface[:state] =~ /UP/
	end

	def same_line_1(context, iface, iface_id)
		context.readline_match_block(/Input:  (?<input_errors>\d+) input errors, (?<runts>\d+) runts, (?<giants>\d+) giants, (?<throttles>\d+) throttles/) do |block|
			#####
			block.warning_ordinary(iface, :input_errors, self) 
			block.warning_ordinary(iface, :runts, self) 
			block.warning_ordinary(iface, :giants, self) 
			block.warning_ordinary(iface, :throttles, self) 
		end
		context.readline_match_block(/(?<crc>\d+) CRC, (?<frame>\d+) frame, - overruns, (?<aborts>\d+) aborts/) do |block|
			block.warning_serious(iface, :crc, self) 
			block.warning_ordinary(iface, :frame, self) 
			block.warning_ordinary(iface, :aborts, self) 
		end
		context.readline_match_block(/Output: (?<output_errors>\d+) output errors, - underruns, - buffer failures/) do |block|
			block.warning_ordinary(iface, :output_errors, self) 
		end
		context.readline_match_block(/(?<aborts>\d+) aborts, (?<deferred>\d+) deferred, (?<collisions>\d+) collisions, (?<last_collisions>\d+) late collisions/) do |block|
			block.warning_ordinary(iface, :aborts, self) 
			block.warning_ordinary(iface, :deferred, self) 
			block.warning_ordinary(iface, :collisions, self) 
			block.warning_ordinary(iface, :last_collisions, self) 
		end
			
		context.readline_match_block(/(?<lost_carrier>\d+) lost carrier/) do |block|
			block.warning_ordinary(iface, :lost_carrier, self) 
		end
	end

	def parse_loopback(context)
		iface = {}
		iface_id = nil
		context.readline_match_block(/(?<iface_id>LoopBack\d+) current state\s?:\s?(?<state>.*)/) do |block|
			iface_id = block[:iface_id]
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :state)
		end
		same_line_2(context, iface, iface_id)
	end

	def parse_vlanif(context)
		iface = {}
		iface_id = nil
		context.readline_match_block(/(?<iface_id>.*) current state: (?<state>.*)/) do |block|
			iface_id = block[:iface_id]
			useful[:interface][iface_id] = iface
			block.update(iface, :iface_id)
			block.update(iface, :state)
		end
		same_line_2(context, iface, iface_id)
	end

	def same_line_2(context, iface, iface_id)
		context.readline_match_block(/Line protocol current state: (?<proto_state>.*)/) do |block|
			block.update(iface, :proto_state)
		end
		context.readline_match_block(/Description: (?<description>.*)/) do |block|
			block.update(iface, :description)
		end
		context.readline_match_block(/Internet (?<addr>.*)/) do |block|
			if block[:addr] =~ /Address (.*) Primary/
				block.update(iface, :ip_addr, $1)
			end
		end
		context.readline_match_block(/Hardware Address: (?<mac>.*)/) do |block|
			block.update(iface, :mac)
		end

		if iface[:state] =~ /UP/
			context.readline_match_block(/input, \d+ bytes, (?<input_drops>\d+) drops/) do |block|
				block.warning_ordinary(iface, :input_drops, self) 
			end
			context.readline_match_block(/output, \d+ bytes, (?<output_drops>\d+) drops/) do |block|
				block.warning_ordinary(iface, :output_drops, self) 
			end
		end
	end

end

			
